package im

import (
	"context"
	"fmt"
	"github.com/flipped-aurora/gin-vue-admin/server/global"
	_const "github.com/flipped-aurora/gin-vue-admin/server/global/const"
	request_model "github.com/flipped-aurora/gin-vue-admin/server/model/im/request"
	"github.com/flipped-aurora/gin-vue-admin/server/model/im/response"
	"github.com/flipped-aurora/gin-vue-admin/server/utils/request"
	"github.com/mitchellh/mapstructure"
	"github.com/pkg/errors"
	"go.uber.org/zap"
	"strconv"
	"time"
)

// 包含im模块公共的service方法，如：系统级用户token、用户token等
type IMCommonService struct{}

var IMCommonServiceApp = new(IMCommonService)

// GetUserToken 获取用户token
func (i *IMCommonService) GetUserToken(ctx context.Context, userID string, platformID int) (string, int64, error) {
	if _, ok := _const.PlatformIDs[platformID]; !ok {
		return "", 0, errors.Errorf("unrecognized platform_id : %d", platformID)
	}

	var userTokenUrl = _const.OpenImServerAddress + "/auth/get_user_token"
	var reqData = request_model.IMUserTokenRequest{
		UserID:     userID,
		PlatformID: platformID,
	}
	// 从缓存中获取adminToken
	adminToken, errToken := global.IMAdminTokenCache.Get(ctx)
	if errToken != nil {
		global.GVA_LOG.Error("获取用户token失败",
			zap.String("uri", "GetUserToken"),
			zap.String("err_message", "获取adminToken失败"),
			zap.Error(errToken))
		return "", 0, fmt.Errorf("failed get token cache: %w", errToken)
	}

	var headers = make(map[string]string, 1)
	headers[request_model.OpenIMOperationIDHeader] = strconv.Itoa(time.Now().Second())
	headers[request_model.OpenIMTokenHeader] = adminToken.(string)
	var openImResp = response.OpenImResponse{}
	var _, errReq = request.HttpRequest(userTokenUrl, request.POST, headers, request.EmptyParams, reqData, &openImResp)
	if errReq != nil {
		global.GVA_LOG.Error("获取用户token失败",
			zap.String("user_id", userID),
			zap.String("uri", "GetUserToken"),
			zap.String("err_message", "请求im获取用户token失败"),
			zap.Error(errReq))
		return "", 0, errReq
	}

	if openImResp.ErrCode != 0 {
		global.GVA_LOG.Error("获取用户token失败",
			zap.String("user_id", userID),
			zap.String("uri", "GetUserToken"),
			zap.Int("err_code", openImResp.ErrCode),
			zap.String("err_dlt", openImResp.ErrDlt),
			zap.String("err_message", openImResp.ErrMsg))
		return "", 0, errors.Errorf("unexpected openim code %s, err_dlt: %s",
			openImResp.ErrCode, openImResp.ErrDlt)
	}

	var tokenData = response.TokenResponseData{}

	if err := mapstructure.Decode(openImResp.Data, &tokenData); err != nil {
		return "", 0, errors.Errorf("user_token_data mapstruct failed! %w, raw_data=%v",
			err, openImResp.Data)
	}

	if tokenData.ExpireTimeSeconds <= 0 {
		global.GVA_LOG.Error("获取用户token失败",
			zap.String("user_id", userID),
			zap.String("uri", "GetUserToken"),
			zap.String("err_message", "user_toke_expired"))
		return "", 0, errors.Errorf("expired user token: %d", tokenData.Token)
	}

	return tokenData.Token, tokenData.ExpireTimeSeconds, nil
}
